﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

namespace ThuatToanKNN.Cores
{
    public class XuLy: KNN_Algorithms
    {
        #region "[Thuật toán KNN]"
        /// <summary>
        /// Thuật toán KNN
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public override string KNN(string path)
        {
            string strresult = string.Empty;
            try
            {
                //đọc file txt
                DTO.Input input = ReadFile(path);
                if (input != null)
                {
                    if (CheckNumeric(input.MauHuanLuyen[0].DanhSachTenThuocTinh, input.MauCanPhanLop))
                    {
                        //chuyển thông tin các mẫu huấn luyện thành danh sách các thông tin mẫu huấn luyện
                        List<DTO.MauHuanLuyen> mauHuanLuyens = new List<DTO.MauHuanLuyen>();
                        foreach (DTO.ThuocTinh item in input.MauHuanLuyen)
                        {
                            DTO.MauHuanLuyen info = new DTO.MauHuanLuyen();
                            info.GiaTris = ConvertListDoubleToListString(item.DanhSachTenThuocTinh);
                            info.KetQua = item.MauKetQua;

                            mauHuanLuyens.Add(info);
                        }

                        //chuyễn thông tin từ mẫu cần phân lớp thành danh sách các các giá trị cần so sánh
                        List<double> doubleResutls = ConvertListDoubleToListString(input.MauCanPhanLop);

                        if (mauHuanLuyens.Count == 0 || doubleResutls.Count == 0)
                            return strresult;

                        //Tìm giá trị lớn nhất cho mỗi cột dữ liệu

                        //chuyễn thành cột.
                        List<DTO.Cot> columnData = ConvertListCotToMauHuanLuyen(ConvertListMauHuanLuyenToListThuocTinh(input.MauHuanLuyen), input.M, input.N);

                        //danh sách các giá trị lớn nhất của từng cột
                        List<double> dMaxs = new List<double>();
                        foreach (DTO.Cot itemCot in columnData)
                        {
                            double maxInfo = TimMax(itemCot.Cots);
                            dMaxs.Add(maxInfo);
                        }

                        List<double> redMax = new List<double>();

                        //tìm max với dãy số kết quả.
                        for (int i = 0; i < dMaxs.Count; i++)
                        {
                            double maxInfo = Math.Max(dMaxs[i], doubleResutls[i]);
                            redMax.Add(maxInfo);
                        }

                        //tính lại danh sách các mẫu huấn luyện.
                        List<DTO.MauHuanLuyen> mauHuanLuyen = TinhLaiMauHuanLuyen(ConvertListMauHuanLuyenToListThuocTinh(input.MauHuanLuyen), redMax);

                        //danh sách các giá trị kết quả sau khi chia cho số lớn nhất.
                        doubleResutls = RutGonMangGiaTri(doubleResutls, redMax);

                        //tính khoản cách euclide
                        List<DTO.KhoanCachEuclide> listKhoanCachEuclide = TinhKhoanCachEuclide(mauHuanLuyen, doubleResutls);

                        //sắp xếp tăng dần.
                        listKhoanCachEuclide = listKhoanCachEuclide.OrderBy(p => p.GiaTri).ToList();

                        //lấy danh sách khoản cách euclide theo k gần nhất.
                        listKhoanCachEuclide = TimLangGiengGanNhat(listKhoanCachEuclide, input.K);

                        //TH1: nếu số lượng khoản cách nào nhiều nhất thì chọn kết quả đó làm kết quả phân lớp
                        strresult = TimPhanLopChoTruongHop01(listKhoanCachEuclide);
                        if (strresult == string.Empty)
                        {
                            //TH2: nếu như kết quả của các khoản cách bằng nhau thì ta tính trung bình các khoản cách, chọn giá trị nhỏ nhất.
                            strresult = TimPhanLopChoTruongHop02(listKhoanCachEuclide);
                        }
                    }
                    else
                    {
                        //kiểu dữ liệu nominal
                        List<DTO.GomNhom> DemKhoanCachMahattan = DanhSachKetQuaTinhBangMahatan(input.MauCanPhanLop, input.MauHuanLuyen);
                        strresult = TimLangGiengTrongMahatan(DemKhoanCachMahattan, input.K);
                    }
                }
                
            }
            catch { }
            return strresult;
        }
        #endregion

        #region "[Tìm người láng giềng gần nhất trong khoan cách mahatan]"
        /// <summary>
        /// Tìm người láng giềng gần nhất trong khoan cách mahatan
        /// </summary>
        /// <param name="_demKhoanCachMahattan"></param>
        /// <returns></returns>
        private string TimLangGiengTrongMahatan(List<DTO.GomNhom> _demKhoanCachMahattan, int k)
        {
            string strResult = string.Empty;
            try { 
                //tìm phân lớp nào xuất hiện nhiều nhất trong khoản k thì phân lớp đó chính là phân lớp kết quả
                List<DTO.GomNhom> listgomnhom = GomNhomMahatan(_demKhoanCachMahattan).OrderBy(p=>p.SoLuong).ToList();

                List<DTO.GomNhom> gnResult = new List<DTO.GomNhom>();
                if (listgomnhom.Count > k)
                {
                    for (int i = 0; i < k; i++)
                    {
                        gnResult.Add(listgomnhom[i]);
                    }
                    listgomnhom = gnResult;
                }

                //tìm max
                DTO.GomNhom Max = TimMaxTrongGomNhom(listgomnhom);
                bool isCheck = Check(Max, listgomnhom);
                if (!isCheck)
                {
                    strResult = Max.Ten;
                }
                else
                { 
                    //lấy danh sách các nhóm có giá trị bằng max
                    List<DTO.GomNhom> listMax = listgomnhom.Where(p => p.SoLuong == Max.SoLuong).ToList();

                    //tính khoản cách trung bình của từng phần tử.
                    List<DTO.KhoanCachEuclide> listAVG = TinhTrungBinhKhoanCach(listMax);
                    DTO.KhoanCachEuclide ItemResultInfo = TimGiaTriTrungBinhNhoNhat(listAVG);
                    strResult = ItemResultInfo.KetQua;
                }
            }
            catch { }
            return strResult;
        }

        #endregion

        #region "[Gom nhóm trong mahatan]"
        /// <summary>
        /// Gom nhóm trong mahatan
        /// </summary>
        /// <param name="_demKhoanCachMahattan"></param>
        /// <returns></returns>
        private List<DTO.GomNhom> GomNhomMahatan(List<DTO.GomNhom> _demKhoanCachMahattan)
        {
            List<DTO.GomNhom> listResult = new List<DTO.GomNhom>();
            try {
                foreach (DTO.GomNhom item in _demKhoanCachMahattan)
                { 
                    if(CheckExistInListGomNhom(listResult,item.Ten)==false ){
                        DTO.GomNhom info = new DTO.GomNhom();
                        info.Ten = item.Ten;
                        info.SoLuong = _demKhoanCachMahattan.Where(p => p.Ten.Trim().CompareTo(item.Ten.Trim()) == 0).ToList().Count;

                        listResult.Add(info);
                    }
                }
            }
            catch { }
            return listResult;
        }

        #region "[Kiểm tra phần tử tồn tại trong mảng gom nhóm]"
        private bool CheckExistInListGomNhom(List<DTO.GomNhom> listResult, string Item)
        {
            bool issucess = false;
            if (listResult.Count == 0)
                return issucess;
            foreach (DTO.GomNhom item in listResult)
            {
                if (item.Ten.Trim().CompareTo(Item.Trim()) == 0)
                    return true;
            }
            return issucess;
        }
        #endregion

        #endregion

        #region "[tính trung bình khoản cách]"
        /// <summary>
        /// Gom nhóm khoản cách
        /// </summary>
        /// <param name="_demKhoanCachMahattan"></param>
        /// <returns></returns>
        private List<DTO.KhoanCachEuclide> TinhTrungBinhKhoanCach(List<DTO.GomNhom> _demKhoanCachMahattan)
        {
            List<DTO.KhoanCachEuclide> listResult = new List<DTO.KhoanCachEuclide>();
            try {
                for (int i = 0; i < _demKhoanCachMahattan.Count; i++)
                {
                    if (CheckExistInListEulide(listResult, _demKhoanCachMahattan[i].Ten.Trim()) == false)
                    {
                        DTO.KhoanCachEuclide info = new DTO.KhoanCachEuclide();
                        info.KetQua = _demKhoanCachMahattan[i].Ten.Trim();
                        info.GiaTri=0;
                        List<DTO.GomNhom> listTemp = _demKhoanCachMahattan.Where(p => p.Ten.Trim().CompareTo(_demKhoanCachMahattan[i].Ten.Trim()) == 0).ToList();

                        foreach (DTO.GomNhom item in listTemp)
                        {
                            info.GiaTri += item.SoLuong;
                        }
                        info.GiaTri /= listTemp.Count;

                        listResult.Add(info);
                    }


                }
            }
            catch { }
            return listResult;
        }
        #endregion

        #region "[Kiểm tra 1 phần tử có tồn tại trong mảng khoản cách euclide]"
        /// <summary>
        /// Kiểm tra 1 phần tử có tồn tại trong mảng khoản cách euclide
        /// </summary>
        /// <param name="_listResult"></param>
        /// <param name="_item"></param>
        /// <returns></returns>
        private bool CheckExistInListEulide(List<DTO.KhoanCachEuclide> _listResult, string _item)
        {
            bool isSuccess = false;
            try {
                if (_listResult.Count == 0)
                    return false;
                foreach (DTO.KhoanCachEuclide item in _listResult)
                {
                    if (item.KetQua.Trim().CompareTo(_item.Trim()) == 0)
                        return true;
                }
            }
            catch { }
            return isSuccess;
        }
        #endregion

        #region "[Tìm danh sách kết quả sau khi tính bằng đỗ do mahatan]"
        /// <summary>
        /// Tìm danh sách kết quả sau khi tính bằng đỗ do mahatan
        /// </summary>
        /// <param name="_mauCanPhanLop">danh sách các thuộc tính cần phân lớp</param>
        /// <param name="_mauHuanLuyen">danh sách các mẫu huấn luyện</param>
        /// <returns></returns>
        private List<DTO.GomNhom> DanhSachKetQuaTinhBangMahatan(List<string> _mauCanPhanLop, List<DTO.ThuocTinh> _mauHuanLuyen)
        {
            List<DTO.GomNhom> listResult = new List<DTO.GomNhom>();
            try {
                foreach (DTO.ThuocTinh item in _mauHuanLuyen)
                {
                    DTO.GomNhom result = new DTO.GomNhom();
                    result.Ten = item.MauKetQua;
                    result.SoLuong = 0;
                    for (int i = 0; i < _mauCanPhanLop.Count; i++)
                    {
                        int khoancachMahatan = Mahatan(_mauCanPhanLop[i], item.DanhSachTenThuocTinh[i]);
                        result.SoLuong += khoancachMahatan;
                    }
                    listResult.Add(result);
                }
            }
            catch { }
            return listResult;
        }
        #endregion

        #region "[tính độ do mahatan]"
        /// <summary>
        /// tính độ do mahatan
        /// </summary>
        /// <param name="a">chuỗi kết quả</param>
        /// <param name="b">chuỗi thành phần</param>
        /// <returns></returns>
        private int Mahatan(string a, string b)
        {
            int iResult = 0;
            try {
                if (a.CompareTo(b) == 0)
                    iResult = 0;
                else
                    iResult = 1;
            }
            catch { }
            return iResult;
        }
        #endregion

        #region "[Đọc file]"
        /// <summary>
        /// đọc file
        /// </summary>
        /// <param name="_strPath">đường dẫn</param>
        /// <returns></returns>
        public override DTO.Input ReadFile(string _strPath)
        {
            DTO.Input objResult = null;
            try {
                StreamReader reader = new StreamReader(_strPath);
                while (reader.EndOfStream == false)
                { 
                    //đọc từng dòng trong file txt

                    //lấy số lượng mẫu
                    string soluongmautrongtaphuanluyen = reader.ReadLine();
                   
                    int soLuongMau = -1;
                    try
                    {
                        soLuongMau = int.Parse(GetValue(soluongmautrongtaphuanluyen));
                    }
                    catch { }
                    if (soLuongMau == -1)
                        return objResult;
                    //lấy số lượng thuộc tính trong mỗi mẫu
                    string soluongthuoctinh = reader.ReadLine();
                    int soLuongThuocTinh = -1;
                    try {
                        soLuongThuocTinh = int.Parse(GetValue(soluongthuoctinh));
                    }
                    catch { }
                    if (soLuongThuocTinh == -1)
                        return objResult;

                    //lấy số lượng người láng giềng gần nhất.
                    string soluongnguoilanggieng = reader.ReadLine();
                    int soLuongNguoiLangGieng = -1;
                    try
                    {
                        soLuongNguoiLangGieng = int.Parse(GetValue(soluongnguoilanggieng));
                    }
                    catch { }
                    if (soLuongNguoiLangGieng == -1)
                        return objResult;

                    //Lấy mẫu cần phân lớp.
                    string mauPhanLop = reader.ReadLine();
                    if (mauPhanLop.CompareTo("U:") != 0)
                        return objResult;
                    mauPhanLop = reader.ReadLine();
                    List<string> listMauPhanLops = mauPhanLop.Split(';').ToList();
                    if (listMauPhanLops.Count == 0)
                        return objResult;

                    //lấy danh sách các tập huấn luyện
                    string taphuanluyen = reader.ReadLine();
                    if (taphuanluyen.CompareTo("T:") != 0)
                        return objResult;
                    List<DTO.ThuocTinh> listtapHuanLuyen = new List<DTO.ThuocTinh>();
                    for (int i = 0; i < soLuongMau; i++)
                    {
                        string mauhuanluyen = reader.ReadLine();
                        DTO.ThuocTinh thuocTinhInfo = new DTO.ThuocTinh();
                        List<string> maus = mauhuanluyen.Split(';').ToList();
                        thuocTinhInfo.MauKetQua = maus[maus.Count - 1];
                        maus.RemoveAt((maus.Count - 1));
                        thuocTinhInfo.DanhSachTenThuocTinh = maus;

                        listtapHuanLuyen.Add(thuocTinhInfo);
                    }

                    //gán vào đối tượng kết quả.
                    objResult = new DTO.Input();
                    objResult.K = soLuongNguoiLangGieng;
                    objResult.M = soLuongMau;
                    objResult.N = soLuongThuocTinh;
                    objResult.MauCanPhanLop = listMauPhanLops;
                    objResult.MauHuanLuyen = listtapHuanLuyen;
                }
                reader.Close();
            }
            catch { }
            return objResult;
        }
        #endregion

        #region "[lấy giá trị trong regex]"
        /// <summary>
        /// lấy giá trị trong regex
        /// </summary>
        /// <param name="_str"></param>
        /// <returns></returns>
        public string GetValue(string _str)
        {
            string strResult = string.Empty;
            try {
                Regex regex1 = new Regex(@"\d+");
                Match mc1 = regex1.Match(_str);
                strResult = mc1.Value;
            }
            catch { }
            return strResult;
        }
        #endregion

        #region "[Ghi File]"
        public override void WriteFile(string _strPath, string _nameFile)
        {
            try {
                StreamWriter writer = new StreamWriter(_strPath);
                writer.Write(_nameFile);
                writer.Flush();
                writer.Close();
            }
            catch { }
        }
        #endregion

        #region "[Tìm phân lớp cho trường hợp 1]"
        /// <summary>
        /// Tìm phân lớp cho trường hợp 1
        /// </summary>
        /// <param name="_list">danh sách các khoản cách euclide</param>
        /// <returns></returns>
        public string TimPhanLopChoTruongHop01(List<DTO.KhoanCachEuclide> _list)
        {
            string strResult = string.Empty;
            try {
                List<DTO.GomNhom> gomnhoms = GomNhomPhanTu(_list);

                DTO.GomNhom Max = TimMaxTrongGomNhom(gomnhoms);
                bool isCheck = Check(Max, gomnhoms);
                if (!isCheck)
                {
                    strResult = Max.Ten;
                }
            }
            catch { }
            return strResult;
        }
        #endregion

        #region "[Tìm Phân lớp cho trường hợp 2]"
        /// <summary>
        /// Tìm Phân lớp cho trường hợp 2
        /// </summary>
        /// <param name="_list"></param>
        /// <returns></returns>
        public string TimPhanLopChoTruongHop02(List<DTO.KhoanCachEuclide> _list)
        {
            string strResult = string.Empty;
            try {
                List<DTO.GomNhom> gomnhoms = GomNhomPhanTu(_list);
                //lấy danh sách các phần tử có số lượng trùng nhau.
                DTO.GomNhom Max = TimMaxTrongGomNhom(gomnhoms);

                List<DTO.GomNhom> result = new List<DTO.GomNhom>();
                result.Add(Max);
                if (gomnhoms.Count > 1)
                {
                    for (int i = 1; i < gomnhoms.Count; i++)
                    {
                        if (Max.SoLuong == gomnhoms[i].SoLuong)
                        {
                            if (Max.Ten.Trim().CompareTo(gomnhoms[i].Ten.Trim()) != 0)
                                result.Add(gomnhoms[i]);
                        }
                    }
                }

                //tính trung bình
                List<DTO.KhoanCachEuclide> agv = TinhTrungBinhEuclide(_list, result);
                DTO.KhoanCachEuclide ItemResultInfo = TimGiaTriTrungBinhNhoNhat(agv);
                strResult = ItemResultInfo.KetQua;
            }
            catch { }
            return strResult;
        }
        #endregion

        #region "[tìm giá trị trung bình nhỏ nhất]"
        /// <summary>
        /// tìm giá trị trung bình nhỏ nhất
        /// </summary>
        /// <param name="agv">danh sách các khoản cách trung bình</param>
        /// <returns></returns>
        public DTO.KhoanCachEuclide TimGiaTriTrungBinhNhoNhat(List<DTO.KhoanCachEuclide> agv)
        {
            DTO.KhoanCachEuclide itemResult = agv[0];
            try {
                if (agv.Count > 1)
                {
                    for (int i = 1; i < agv.Count; i++)
                    {
                        if (itemResult.GiaTri > agv[i].GiaTri)
                        {
                            itemResult = agv[i];
                        }
                    }
                }
            }
            catch { }
            return itemResult;
        }
        #endregion

        #region "[Kiểm tra giá trị trùng]"
        /// <summary>
        /// Kiểm tra giá trị trùng
        /// </summary>
        /// <param name="Max"></param>
        /// <param name="gomnhoms"></param>
        /// <returns></returns>
        public bool Check(DTO.GomNhom Max, List<DTO.GomNhom> gomnhoms)
        {
            bool isSuccess = false;
            try {
                foreach (DTO.GomNhom item in gomnhoms)
                {
                    if (Max.SoLuong == item.SoLuong)
                    {
                        if (Max.Ten.Trim().CompareTo(item.Ten.Trim()) != 0)
                            isSuccess = true;
                    }
                }
            }
            catch { }
            return isSuccess;
        }
        #endregion

        #region "[Tìm max trong danh sách gom nhóm]"
        /// <summary>
        /// Tìm max trong danh sách gom nhóm
        /// </summary>
        /// <param name="gomnhoms">danh sách các đối tượng gom nhóm</param>
        /// <returns></returns>
        public DTO.GomNhom TimMaxTrongGomNhom(List<DTO.GomNhom> gomnhoms)
        {
            DTO.GomNhom itemResult = gomnhoms[0];
            try { 
                foreach(DTO.GomNhom item in gomnhoms)
                {
                    if (itemResult.SoLuong < item.SoLuong)
                    {
                        itemResult = item;
                    }
                }
            }
            catch { }
            return itemResult;
        }
        #endregion

        #region "[Gom nhóm]"
        public List<DTO.GomNhom> GomNhomPhanTu(List<DTO.KhoanCachEuclide> _list)
        {
            List<DTO.GomNhom> listResult = new List<DTO.GomNhom>();
            try {
                for (int i = 0;i<_list.Count;i++)
                {
                    if (listResult.Count == 0 || Tim(listResult, _list[i].KetQua)==false)
                    {
                        DTO.GomNhom info = new DTO.GomNhom();
                        info.Ten = _list[i].KetQua;
                        info.SoLuong = 1;
                        for (int j = i + 1; j < _list.Count; j++)
                        {
                            if (_list[i].KetQua.Trim().CompareTo(_list[j].KetQua.Trim()) == 0)
                            {
                                info.SoLuong++;
                            }
                        }
                        listResult.Add(info);
                    }
                }
            }
            catch { }
            return listResult;
        }
        #endregion

        #region "[tìm 1 phần tử có xuất hiện trong mảng]"
        /// <summary>
        /// tìm 1 phần tử có xuất hiện trong mảng
        /// </summary>
        /// <param name="listResult">danh sách các phần tử gom nhóm</param>
        /// <param name="Item">phần tử cần tìm</param>
        /// <returns></returns>
        public bool Tim(List<DTO.GomNhom> listResult, string name)
        {
            bool isSuccess = false;
            try {
                foreach (DTO.GomNhom kj in listResult)
                {
                    if (kj.Ten.Trim().CompareTo(name) == 0)
                        return true;
                }
            }
            catch { }
            return isSuccess;

        }
        #endregion

        #region "[Tính trung bình euclide]"
        /// <summary>
        /// Tính trung bình euclide
        /// </summary>
        /// <param name="listKhoanCachEuclide">danh sách các khoản cách euclide</param>
        /// <returns></returns>
        public List<DTO.KhoanCachEuclide> TinhTrungBinhEuclide(List<DTO.KhoanCachEuclide> listKhoanCachEuclide,List<DTO.GomNhom> _listGomNhom)
        {
            List<DTO.KhoanCachEuclide> listResult = new List<DTO.KhoanCachEuclide>();
            try {
                foreach (DTO.GomNhom item in _listGomNhom)
                {
                    if (listResult.Count == 0 || (!Check(listResult, item.Ten)))
                    {
                        int i = 1;
                        DTO.KhoanCachEuclide info = new DTO.KhoanCachEuclide();
                        info.KetQua = item.Ten;
                        info.GiaTri = 0;
                        foreach (DTO.KhoanCachEuclide item1 in listKhoanCachEuclide)
                        {
                            if (item.Ten.Trim().CompareTo(item1.KetQua.Trim()) == 0)
                            {
                                info.GiaTri += item1.GiaTri;
                                i++;
                            }
                        }
                        info.GiaTri = (info.GiaTri / i);

                        listResult.Add(info);
                    }
                    
                }
            }
            catch { }
            return listResult;
        }

        private bool Check(List<DTO.KhoanCachEuclide> listResult, string p)
        {
            bool isSuccess = false;
            try { 
                foreach(DTO.KhoanCachEuclide item in listResult)
                {
                    if (item.KetQua.Trim().CompareTo(p.Trim()) == 0)
                        return true;
                }
            }
            catch { }
            return isSuccess;
        }
        #endregion
        
        #region "[Tìm phần tử trùng]"
        /// <summary>
        /// Tìm phần tử trùng
        /// </summary>
        /// <param name="listKhoanCachEuclide">danh sách các khoản cách euclide</param>
        /// <param name="phantu">phần tử cần kiểm tra</param>
        /// <returns></returns>
        public DTO.KhoanCachEuclide TimPhanTuTrung(List<DTO.KhoanCachEuclide> listKhoanCachEuclide, DTO.KhoanCachEuclide phantu)
        {
            DTO.KhoanCachEuclide info = phantu;
            try {
                int n = 1;
                foreach (DTO.KhoanCachEuclide item in listKhoanCachEuclide)
                {
                    if (phantu.KetQua.CompareTo(item.KetQua) == 0)
                    {
                        n++;
                        info.GiaTri += item.GiaTri;
                    }
                }
                info.GiaTri = (info.GiaTri / n);
            }
            catch { }
            return info;
        }
        #endregion

        #region "[Tính danh sách người láng giềng gần nhất]"
        /// <summary>
        /// Tính danh sách người láng giềng gần nhất
        /// </summary>
        /// <param name="listKhoanCachEuclide">danh sách các khoản cách euclide</param>
        /// <param name="K">số lượng người láng giềng</param>
        /// <returns></returns>
        public List<DTO.KhoanCachEuclide> TimLangGiengGanNhat(List<DTO.KhoanCachEuclide> listKhoanCachEuclide, int K)
        {
            List<DTO.KhoanCachEuclide> listResult = new List<DTO.KhoanCachEuclide>();
            try {
                for (int i = 0; i < K;i++ )
                {
                    listResult.Add(listKhoanCachEuclide[i]);
                }
            }
            catch { }
            return listResult;
        }
        #endregion

        #region "[Tính khoản các euclide]"
        /// <summary>
        /// Tính khoản các euclide
        /// </summary>
        /// <param name="mauHuanLuyen">danh sách các mẫu huấn luyện</param>
        /// <param name="doubleResutls">danh sách các giá trị max</param>
        /// <returns></returns>
        public List<DTO.KhoanCachEuclide> TinhKhoanCachEuclide(List<DTO.MauHuanLuyen> mauHuanLuyen, List<double> doubleResutls)
        {
            List<DTO.KhoanCachEuclide> listResult = new List<DTO.KhoanCachEuclide>();
            try {
                foreach (DTO.MauHuanLuyen item in mauHuanLuyen)
                {
                    DTO.KhoanCachEuclide info = new DTO.KhoanCachEuclide();
                    info.KetQua = item.KetQua;
                    info.GiaTri = Eclide(item.GiaTris, doubleResutls);
                    listResult.Add(info);
                }
            }
            catch { }
            return listResult;
        }
        #endregion

        #region "[Khoản các Euclide]"
        /// <summary>
        /// Khoản các Euclide
        /// </summary>
        /// <param name="_listInput">danh sách các thuộc tính của tập huấn luyện</param>
        /// <param name="_listdMax">danh sách các giá trị max</param>
        /// <returns></returns>
        public double Eclide(List<double> _listHuanLuyen, List<double> _listPhanLop)
        {
            double dResult = 0;
            try {
                for (int i = 0; i < _listHuanLuyen.Count; i++)
                {
                    dResult += Math.Pow(_listHuanLuyen[i] - _listPhanLop[i], 2);
                }
                dResult =Math.Round( Math.Sqrt(dResult),3);
            }
            catch { }
            return dResult;
        }
        #endregion

        #region "[chuyễn danh sách các chuỗi thành danh sách các số kiểu double]"
        /// <summary>
        /// chuyễn danh sách các chuỗi thành danh sách các số kiểu double
        /// </summary>
        /// <param name="listInput">danh sách các chuỗi</param>
        /// <returns></returns>
        public List<double> ConvertListDoubleToListString(List<string> listInput)
        {
            List<double> listresult = new List<double>();
            try {
                foreach (string s in listInput)
                {
                    double dTemp = double.Parse(s);
                    listresult.Add(dTemp);
                   
                }
            }
            catch { }
            return listresult;
        }
        #endregion

        #region "[Chuyển dsanh sách Thuộc tính thành mẫu huấn luyện]"
        /// <summary>
        /// Chuyển dsanh sách Thuộc tính thành mẫu huấn luyện
        /// </summary>
        /// <param name="_list"></param>
        /// <returns></returns>
        public List<DTO.MauHuanLuyen> ConvertListMauHuanLuyenToListThuocTinh(List<DTO.ThuocTinh> _list)
        {
            List<DTO.MauHuanLuyen> listResult = new List<DTO.MauHuanLuyen>();
            try { 
                foreach(DTO.ThuocTinh item in _list)
                {
                    DTO.MauHuanLuyen listTemp = new DTO.MauHuanLuyen();
                    listTemp.GiaTris = ConvertListDoubleToListString(item.DanhSachTenThuocTinh);
                    listTemp.KetQua = item.MauKetQua;
                    listResult.Add(listTemp);
                }
            }
            catch { }
            return listResult;
        }
        #endregion

        #region "[Chuyển Danh sách các mẫu huấn luyện thành cột]"
        /// <summary>
        /// Chuyển Danh sách các mẫu huấn luyện thành cột
        /// </summary>
        /// <param name="_list">danh sách các mẫu huấn luyện</param>
        /// <returns></returns>
        public List<DTO.Cot> ConvertListCotToMauHuanLuyen(List<DTO.MauHuanLuyen> _list, int soDong, int soCot)
        {
            List<DTO.Cot> cots = new List<DTO.Cot>();
            try {
                for (int icot = 0; icot < soCot; icot++)
                {
                    DTO.Cot cotInfo =new DTO.Cot();
                    cotInfo.Cots = new List<double>();
                    for (int jdong = 0; jdong < soDong; jdong++)
                    {
                        double temp = _list[jdong].GiaTris[icot];
                        cotInfo.Cots.Add(temp);
                    }
                    cots.Add(cotInfo);
                }
                
            }
            catch { }
            return cots;
        }
        #endregion

        #region "[Lấy danh sách các kết quả]"
        /// <summary>
        /// Lấy danh sách các kết quả
        /// </summary>
        /// <param name="_list">danh sách các mẫu huấn luyện</param>
        /// <returns></returns>
        public List<string> LayMauKetQua(List<DTO.MauHuanLuyen> _list)
        {
            List<string> listResult = new List<string>();
            try {
                foreach (DTO.MauHuanLuyen item in _list)
                {
                    listResult.Add(item.KetQua);
                }
            }
            catch { }
            return listResult;
        }
        #endregion

        #region "[Chuyển Danh sách các cột thành mẫu huấn luyện]"
        /// <summary>
        /// Chuyển Danh sách các cột thành mẫu huấn luyện
        /// </summary>
        /// <param name="_list">danh sách các cột</param>
        /// <returns></returns>
        public List<DTO.MauHuanLuyen> ConvertListMauHuanLuyenToCot(List<DTO.Cot> _list, List<string> _listMauKQ)
        {
            List<DTO.MauHuanLuyen> mauHuanLuyens = new List<DTO.MauHuanLuyen>();
            try {
                for (int idong = 0; idong < _list[0].Cots.Count; idong++)
                {
                    DTO.MauHuanLuyen mauInfo = new DTO.MauHuanLuyen();
                    mauInfo.KetQua = _listMauKQ[idong];

                    for (int jcot = 0; jcot < _list.Count; jcot++)
                    {
                        mauInfo.GiaTris.Add(_list[jcot].Cots[idong]);
                    }
                    mauHuanLuyens.Add(mauInfo);
                }
            }
            catch { }
            return mauHuanLuyens;
        }
        #endregion

        #region "[tìm giá trị lớn nhất của dãy số]"
        /// <summary>
        /// tìm giá trị lớn nhất của dãy số
        /// </summary>
        /// <param name="_list">danh sách các dãy số</param>
        /// <returns></returns>
        public double TimMax(List<double> _list)
        {
            double dResult=_list[0];
            try {
                foreach (double item in _list)
                {
                    if (dResult < item)
                        dResult = item;
                }
            }
            catch { }
            return dResult;
        }
        #endregion

        #region "[tính lại mẫu huấn luyện]"
        /// <summary>
        /// tính lại mẫu huấn luyện
        /// </summary>
        /// <param name="_list">danh sách các mẫu huấn luyện cũ</param>
        /// <param name="_dMax">danh sách các giá trị lớn nhất</param>
        /// <returns></returns>
        public List<DTO.MauHuanLuyen> TinhLaiMauHuanLuyen(List<DTO.MauHuanLuyen> _list, List<double> _dMax)
        {
            List<DTO.MauHuanLuyen> listResult = new List<DTO.MauHuanLuyen>();
            try {
                foreach (DTO.MauHuanLuyen item in _list)
                {
                    DTO.MauHuanLuyen info = new DTO.MauHuanLuyen();
                    info.KetQua = item.KetQua;
                    info.GiaTris = RutGonMangGiaTri(item.GiaTris, _dMax);
                    listResult.Add(info);
                }
            }
            catch { }
            return listResult;
        }
        #endregion

        #region "[rút gọn màng giá trị]"
        /// <summary>
        /// rút gọn màng giá trị
        /// </summary>
        /// <param name="_listInput">danh sách các phần tử cần rút gọn</param>
        /// <param name="_listdMax">mảng chứa danh sách các giá trị lớn nhất</param>
        /// <returns></returns>
        public List<double> RutGonMangGiaTri(List<double> _listInput, List<double> _listdMax)
        {
            List<double> listResult = new List<double>();
            try {
                for (int i = 0; i < _listInput.Count; i++)
                {
                    double Max = Math.Round((_listInput[i] / _listdMax[i]), 2);
                    listResult.Add(Max);
                }

            }
            catch { }
            return listResult;
        }
        #endregion

        #region "[Kiểm tra kiểu dữ liệu là numeric hay nominal]"
        /// <summary>
        /// Kiểm tra kiểu dữ liệu là numeric hay nominal
        /// true: kiểu dữ liệu là numeric, false: kiểu dữ liệu là nominal
        /// </summary>
        /// <param name="danhsachmauhuanluyen"></param>
        /// <param name="danhsachmauphanlop"></param>
        /// <returns></returns>
        private bool CheckNumeric(List<string> danhsachmauhuanluyen, List<string> danhsachmauphanlop)
        {
            bool issucess = false;
            try { 
                bool check = false ;
                foreach (string s in danhsachmauhuanluyen)
                {
                    double temp = -1;
                    bool kiemtra = double.TryParse(s, out temp);
                    if (!kiemtra)
                    {
                        return false;
                    }
                    check = true;
                }
                if (check)
                {
                    foreach (string s in danhsachmauphanlop)
                    {
                        double temp = -1;
                        bool kiemtra = double.TryParse(s, out temp);
                        if (!kiemtra)
                        {
                            return false;
                        }
                    }
                    
                }
                issucess = check;
            }
            catch { }
            return issucess;
        }
        #endregion
    }
}
